﻿
namespace Anycmd.Engine.Ac.Catalogs
{
    using System;

    /// <summary>
    /// 表示该接口的实现类是目录类型。目录是对资源的单元划分。目录属于一种分类法，它与普通的分类法的唯一差别是目录具有偏移量。
    /// <example>
    /// 给定一个0到100的实数集合Set{0…100}。
    /// 普通的分类法所做的分类类似这样：
    /// {
    ///     [0…10},
    ///     [10…20},
    ///     [20…50},
    ///     [50…100]
    /// }
    /// 而目录是这样：
    /// {
    ///     {
    ///         [0…10},
    ///         [10…20}
    ///     },
    ///     [20…30},
    ///     {
    ///         [30…35},
    ///         [35…40},
    ///         [40…50},
    ///         {
    ///             [50…60},
    ///             [60…70},
    ///             [70…75},
    ///             [75…80},
    ///         }
    ///     },
    ///     [80…100],
    /// }
    /// </example>
    /// <remarks>
    /// Anycmd对目录的使用几乎遍布所有资源，目录是资源的附加属性，而资源的固有属性只是没有偏移的分类。Anycmd希望在需要的
    /// 时候能够被允许侵入应用系统的数据库设计以保存资源管理员添加的组织属性（这个组织属性可能不止一种，但不管资源管理员在管理资源集
    /// 的时候添加了多少组织属性Anycmd都只会使用你对应的数据库表的一个字段存储）。
    /// 之所以要侵入应用数据库表是为了根据目录对资源集的筛选能够在数据库进程完成而不必加载进应用系统的内存再筛选。
    /// 框架使用那一个字段比如varchar(100)，框架把它的长度再做单元划分，如果一个单元定长为10就可以存储资源管理员添加的10种目录。
    /// 根据目录查询的时候应用系统发出的sql中会截取这个字段的正确的单元。
    /// Anycmd.Ac是个权限框架，也支持实体级的控制。管理资源的时候尽量不推荐使用实体级的控制，首先评估实体属性（在实体属性上可以对资源集进行分类划分），
    /// 如果在实体上的那些固有属性上难以制定出满足安全需求的策略的话再考虑是不是需要目录，尽量使用附加的组织属性去对资源划分单元，按照单元进行控制
    /// 尽量不使用实体级的控制（因为实体太多了，但如果目标实体是主体的话，比如User实体是主体，这个可以实体级控制，由各个主体自主控制自己而不用管理员工作）。
    /// 实体级的控制的开启也需要侵入应用系统的数据库，侵入目标资源表建立“一个”安全字段，这个字段中存储的是这条记录的安全策略，安全策略是跟实体记录一同
    /// 加载进应用系统的内存的，之所以要侵入你的数据库也是因为不应该多一次专门查询Acl策略的查询。
    /// </remarks>
    /// </summary>
    public interface ICatalog
    {
        /// <summary>
        /// 目录唯一标识
        /// </summary>
        Guid Id { get; }

        /// <summary>
        /// 编码。
        /// <remarks>
        /// 设计通过以父级目录编码为前缀来表现层级关系而不记录ParentId也不记录层级的Level。
        /// </remarks>
        /// </summary>
        string Code { get; }

        /// <summary>
        /// 名称
        /// </summary>
        string Name { get; }

        /// <summary>
        /// 父目录编码
        /// <remarks>
        /// 设计通过以父级目录编码为前缀来表现层级关系而不记录ParentId也不记录层级的Level。
        /// 目录上不封顶下不封底，如果需要向上扩展则需定义“零”编码，定义编码的“正负”属性。
        /// </remarks>
        /// </summary>
        string ParentCode { get; }

        /// <summary>
        /// 目录分类。
        /// </summary>
        string CategoryCode { get; }

        /// <summary>
        /// 说明
        /// </summary>
        string Description { get; }

        /// <summary>
        /// 是否有效。1有效，0无效
        /// </summary>
        int IsEnabled { get; }

        int SortCode { get; }
    }
}
